package org.dandelion.papercheck.util;

import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.List;

@Component
public class ChineseHash implements Hash {

    private int A = 0x2301;
    private int B = 0x6745;
    private int C = 0xAB89;
    private int D = 0xEFCD;

    private static final int HASH_LEN = 64;

    public int[] wordHash(String src) {
        A = 0x2301;
        B = 0x6745;
        C = 0xAB89;
        D = 0xEFCD;

        int[] rst = new int[HASH_LEN];
        byte[] srcBytes = src.getBytes(StandardCharsets.UTF_8);
        for (byte srcByte : srcBytes) {
            procByte(srcByte);
        }

        to64Array(rst, 0, 16, A);
        to64Array(rst, 16, 32, B);
        to64Array(rst, 32, 48, C);
        to64Array(rst, 48, 64, D);

        return rst;
    }

    @Override
    public List<int[]> multiWordsHash(List<String> words) {
        return null;
    }


    public int F1(int X, int Y, int Z) {
        return Y ^ (X | (~Z));
    }

    public int F2(int X, int Y, int Z) {
        return (X & Y) | ((~X) & Z);
    }

    public int F3(int X, int Y, int Z) {
        return (X & Z) | (Y & (~Z));
    }

    public int F4(int X, int Y, int Z) {
        return X ^ Y ^ Z;
    }

    public void procByte(byte b) {
        A = A + rotateShift(F1(B, C, D) + (b | (int) b << 8), 7);
        B = B + rotateShift(F2(C, D, A) + ~(b | (int) b << 8), 12);
        C = C + rotateShift(F3(D, A, B) + (~b | (int) b << 8), 15);
        D = D + rotateShift(F4(A, B, C) + (b | ~((int) b << 8)), 5);

/*
        A = rotateShift(F2(A, C, (b | (int)b << 8)), 4);
        B = rotateShift(F3(B, D, (b | (int)b << 8)),9);
        C = rotateShift(F4(C, A, (b | (int)b << 8)),11);
        D = rotateShift(F1(D, B, (b | (int)b << 8)),13);

        A = rotateShift(F3(A, D, (b | (int)b << 8)),3);
        B = rotateShift(F4(B, A, (b | (int)b << 8)), 8);
        C = rotateShift(F2(C, B, (b | (int)b << 8)), 10);
        D = rotateShift(F1(D, C, (b | (int)b << 8)), 14);
*/

    }

    public void to64Array(int[] rst, int from, int to, int num) {
        for (int i = from; i < to; i++) {
            int j = i - from;
            int temp = num;
            temp = (temp >> j) & 1;
            rst[i] = temp;
        }
    }

    public int rotateShift(int num, int i) {
        int low = num & (~(0xFFF << i));
        num = num << i;
        num = num | low;
        return num;
    }
}
